#include "ircid.h"

/* $Id: ircid.c 11 2010-01-19 03:42:37Z karel.tuma $ */
/* $Revision: 11 $ */

char *static_html = NULL;

static char *c_port_ircs(struct ev_loop *loop, char *argv[])
{
/*	if (!ircs_init(loop, 5, argv))
		return "Failed to initialize IRCS server"; */
	return NULL;
}


static	char *c_port_https(struct ev_loop *loop, char *argv[])
{
	if (!http_init(loop, 5, argv))
		return "Failed to initialize HTTPS server";
	return NULL;
}

static	char *c_port_http(struct ev_loop *loop, char *argv[])
{
	DEBUG("creating http server, port=%d connectto=%s connectport=%s", argv[0], argv[1], argv[2]);
	if (!http_init(loop, 3, argv))
		return "Failed to initialize HTTP server";
	return NULL;
}

static	char *c_index(struct ev_loop *l,char *argv[])
{
	/* we dont check for existance, this can be changed while running */
	static_html = argv[0];
	return NULL;
}

static	char *c_chroot(struct ev_loop *l,char *argv[])
{
	if (!geteuid()) {
		chdir(argv[0]);
		if (chroot(".")) {
			perror("chroot");
			return "chroot() failed";
		}
	}
	return NULL;
}

static	char *c_setuid(struct ev_loop *l, char *argv[])
{
	if (!geteuid()) {
		if (setgid(atol(argv[0]))) {
			perror("setgid");
			return "setgid() failed";
		}
		if (setuid(atol(argv[1]))) {
			perror("setuid");
			return "setuid() failed";
		}
	}
	return NULL;
}


char	*parse_cfg(struct ev_loop *loop, FILE *f, int *lineno)
{
	char *err;
	struct {
		char	*opt;
		int	narg;
		char	*(*method)(struct ev_loop *, char *[]);
	} opts[] = {
		{ "setuid", 2, &c_setuid },
		{ "chroot", 1, &c_chroot },
		{ "index", 1, &c_index },
		{ "port_http", 3, &c_port_http },
		{ "port_https", 5, &c_port_https },
		{ "port_ircs", 5, &c_port_ircs },
		{ NULL }
	};
	char ln[512];
	int i, j;
#define SKIP_BLANK(p) \
		while (*p == ' ' || *p == '\t') p++; /* skip whitespace */
#define SKIP_NONBLANK(pe) \
		while (*pe != ' ' && *pe != '\t' && *pe != '#' && *pe) pe++;
	*lineno = 0;
	while (fgets(ln, sizeof(ln)-10, f)) {
		char *p = ln;
		char *pe;
		char **argv;

		if ((pe = strchr(p, '\n')) || (pe = strchr(p, '\r')))
			*pe = 0;
		memcpy(ln + strlen(ln), "\0\0\0\0\0\0", 6);

		(*lineno)++;
		SKIP_BLANK(p);
		if (*p == '#' || !*p) continue; /* ignore line */
		pe = p;
		SKIP_NONBLANK(pe);
		*pe++ = 0;
		printf("trying %s\n", p);
		for (i = 0; opts[i].opt; i++) {
			if (!strcmp(p, opts[i].opt)) {
				/* found opt, collect args now */
				argv = malloc(sizeof(char *) * opts[i].narg);
				for (j = 0; j < opts[i].narg; j++) {
					if (!*pe || *pe == '#') {  return "Insufficient args"; }
					SKIP_BLANK(pe);
					if (!*pe || *pe == '#') { return "Insufficient args"; }
					p = pe;
					SKIP_NONBLANK(pe);
					*pe++ = 0;
					argv[j] = strdup(p);
				}
				if ((err=opts[i].method(loop, argv))) {
					return err;
				}
			}
		}
	}
	fclose(f);
	return NULL;
}

int	main(int argc, char *argv[])
{
	struct ev_loop *loop = ev_default_loop(0);
	int errln = -1;
	FILE *f;
	char *perr;

	if (argc != 2) {
		fprintf(stderr, "usage: %s configfile\n", argv[0]);
		return -1;
	}
	f = fopen(argv[1], "r");
	if (!f) {
		perror(argv[1]);
		return -1;
	}
	if ((perr = parse_cfg(loop, f, &errln))) {
		fclose(f);
		fprintf(stderr, "Config error at line %d: %s\n", errln, perr);
		return -1;
	}
	ev_loop(loop, 0);
	return 0;
}
